package org.hubwork.base.common;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.access.BeanFactoryLocator;
import org.springframework.beans.factory.access.BeanFactoryReference;
import org.springframework.context.access.ContextSingletonBeanFactoryLocator;

public class HubApplicationContext {

	protected static HubApplicationContext instance                      = null;

	  protected boolean                   autoRegister                  = true;

	  protected HubApplicationContext ()
	  {
	    super ();
	    this.autoRegister = true;	    
	  }

	  private static DynamicBeanFactory beanFactory = null;
	  
	  public static DynamicBeanFactory getBeanFactory(){
	    if (beanFactory == null)
	    {
	      synchronized (HubApplicationContext.class) {
	        if (beanFactory == null)
	        {
	          BeanFactoryLocator bfl = ContextSingletonBeanFactoryLocator.getInstance();
	          BeanFactoryReference bf = bfl.useBeanFactory("businessBeanFactory");
	          beanFactory = (DynamicBeanFactory)bf.getFactory();
	          beanFactory.registerShutdownHook ();
	        }
	      }
	    }
	    return beanFactory;
	  }
	  
	  public static HubApplicationContext getInstance ()
	  {
	    if (instance == null)
	    {
	      instance = new HubApplicationContext ();
	    }
	    return instance;
	  }

	  @SuppressWarnings("unchecked")
	  public static <T> T get (String name)
	  {
	    return (T) get (name, null, null);
	  }

	  public static <T> T get (String name, Class<T> clazz)
	  {
	    return get (name, clazz, clazz);
	  }

	  public static <T> T get (Class<T> clazz)
	  {
	    return get (clazz.getCanonicalName (), clazz, clazz);
	  }

	  public static <T, U extends T> T get (Class<T> clazz, Class<U> defImpl)
	  {
	    return get (clazz.getCanonicalName (), clazz, defImpl);
	  }

	  @SuppressWarnings ("unchecked")
	  public static <T, U extends T> T get (String name, Class<T> clazz, Class<U> defImpl)
	  {
	    if (name == null)
	    {
	      name = clazz.getCanonicalName ();
	    }
	    if (DynamicBeanFactory.prototypes.containsKey (name))
	    {
	      try
	      {
	        return (T) BeanUtils.instantiateClass(DynamicBeanFactory.prototypes.get (name));
	      }
	      catch (Exception ex2)
	      {
	        throw new RuntimeException (ex2);
	      }
	    }
	    else if (DynamicBeanFactory.requests.containsKey (name))
	    {
	      return (T) ThreadContext.get (name, DynamicBeanFactory.requests.get (name));
	    }

	    return HubApplicationContext.getBeanFactory ().getBean (name, clazz, defImpl);
	  }
}
